﻿using System.Windows.Controls;
using System.Windows.Media.Imaging;
using DeepEarth.Map.Core;
using DeepEarth.Toolkit.Geometry.Data;
using System.Windows;
using System;
using System.Windows.Media;
namespace DeepEarth.Toolkit.Geometry
{
    public class BitmapLayer : BaseLayer
    {
        const double DefaultMaxBound = 16848;

        Image image;
        WriteableBitmap writeableBitmap;
        GeometryRenderer geometryRenderer;

        bool initialized = false;

        public BitmapLayer()
        {
            geometryRenderer = new GeometryRenderer();
            this.image = new Image();
            image.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
            image.VerticalAlignment = System.Windows.VerticalAlignment.Stretch;
            this.Children.Add(image);
            this.SizeChanged += (o, e) => Initialize();
            Initialize();

            this.LayoutUpdated += new System.EventHandler(BitmapLayer_LayoutUpdated);
        }

        void BitmapLayer_LayoutUpdated(object sender, System.EventArgs e)
        {
            if (!initialized)
            {
                Initialize();
            }
            else
            {
                this.LayoutUpdated -= BitmapLayer_LayoutUpdated;
            }
        }

        void Initialize()
        {
            if (MapInstance!= null && MapInstance.AsFrameworkElement.ActualWidth > 0 && MapInstance.AsFrameworkElement.ActualHeight > 0)
            {
                image.Width = this.ActualWidth;
                image.Height = this.ActualHeight;

                this.writeableBitmap = new WriteableBitmap((int)this.ActualWidth, (int)this.ActualHeight);
                image.Source = writeableBitmap;
                geometryRenderer.WriteableBitmap = writeableBitmap;
                geometryRenderer.MapInstance = this.MapInstance;
                geometryRenderer.Refresh(DefaultMaxBound);
                initialized = true;
            }
        }

        protected override void MapChanged()
        {
            Initialize();
        }

        // http://www.scottlogic.co.uk/blog/colin/2010/06/throttling-silverlight-mouse-events-to-keep-the-ui-responsive/
        bool awaitingRender;

        void CompositionTarget_Rendering(object sender, EventArgs e)
        {
            awaitingRender = false;
            CompositionTarget.Rendering -= CompositionTarget_Rendering;
        }

        protected override void SynchronizeOnFrame()
        {
            // This does prevent the UI from completely locking up
            if (awaitingRender)
            {
                return;
            }

            awaitingRender = true;
            CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);

            if (this.Visibility == Visibility.Visible)
            {
                geometryRenderer.Refresh(DefaultMaxBound);
            }
        }

        protected override void SynchronizeOnEnd()
        {
            if (this.Visibility == Visibility.Visible)
            {
                geometryRenderer.Refresh(DefaultMaxBound);
            }
        }

        public void Add(ShapeGeometry geo)
        {
            geometryRenderer.Geometries.Add(geo);
            geometryRenderer.Refresh(DefaultMaxBound);
        }

        public void Remove(ShapeGeometry geo)
        {
            geometryRenderer.Geometries.Remove(geo);
            geometryRenderer.Refresh(DefaultMaxBound);
        }

        public void Clear()
        {
            geometryRenderer.Geometries.Clear();
            geometryRenderer.Refresh(DefaultMaxBound);
        }
    }
}